/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package entity;

import exception.CustomerAccountDoesNotExistException;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Temporal;
import type.InvoiceStatus;
import type.InvoiceType;

/**
 *
 * @author wei
 */
@Entity(name="CustomerInvoice")
public class CustomerInvoiceEntity extends DataObjectEntity implements Serializable {
    private double amount;
    private double latePenalty;
    private double earlyRebate;
    @Temporal(javax.persistence.TemporalType.DATE)
    private Date dueDate;
    @Temporal(javax.persistence.TemporalType.DATE)
    private Date discountDueDate;
    private InvoiceType type;
    private InvoiceStatus status;
    
    @OneToOne
    private BillingRequestEntity billingRequest;
    @ManyToOne
    CustomerAccountEntity customerAccount;
    @OneToOne(mappedBy="invoice")
    PaymentEntity payment;
    @OneToOne(mappedBy="invoice")
    ReceiptEntity receipt;

    public CustomerInvoiceEntity() {
        super();
    }

    public double getAmount() {
        return amount;
    }

    public void setAmount(double amount) {
        this.amount = amount;
    }

    public BillingRequestEntity getBillingRequest() {
        return billingRequest;
    }

    public void setBillingRequest(BillingRequestEntity billingRequest) {
        this.billingRequest = billingRequest;
    }

    public Date getDiscountDueDate() {
        return discountDueDate;
    }

    public void setDiscountDueDate(Date discountDueDate) {
        this.discountDueDate = discountDueDate;
    }

    public Date getDueDate() {
        return dueDate;
    }

    public void setDueDate(Date dueDate) {
        this.dueDate = dueDate;
    }

    public double getEarlyRebate() {
        return earlyRebate;
    }

    public void setEarlyRebate(double earlyRebate) {
        this.earlyRebate = earlyRebate;
    }

    public double getLatePenalty() {
        return latePenalty;
    }

    public void setLatePenalty(double latePenalty) {
        this.latePenalty = latePenalty;
    }

    public InvoiceStatus getStatus() {
        return status;
    }

    public void setStatus(InvoiceStatus status) {
        this.status = status;
    }

    public InvoiceType getType() {
        return type;
    }

    public void setType(InvoiceType type) {
        this.type = type;
    }

    public CustomerAccountEntity getCustomerAccount() {
        return customerAccount;
    }

    public void setCustomerAccount(CustomerAccountEntity customerAccount) {
        this.customerAccount = customerAccount;
    }

    public PaymentEntity getPayment() {
        return payment;
    }

    public void setPayment(PaymentEntity payment) {
        this.payment = payment;
    }

    public ReceiptEntity getReceipt() {
        return receipt;
    }

    public void setReceipt(ReceiptEntity receipt) {
        this.receipt = receipt;
    }
    
    public void calculatedDueDatesPenaltyAndDiscount() throws CustomerAccountDoesNotExistException{
        if(customerAccount==null || customerAccount.getCreditTerm()==null)
            throw new CustomerAccountDoesNotExistException("Customer account or credit term does not exist");
        CreditTermEntity creditTerm = customerAccount.getCreditTerm();
        
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_MONTH, creditTerm.getMaxRepayTime());
        setDueDate(cal.getTime());
        
        cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_MONTH, creditTerm.getDiscountRepayTime());
        setDiscountDueDate(cal.getTime());
        
        double penalty = getAmount()*creditTerm.getLateCharges();
        setLatePenalty(penalty);
        
        double rebate = getAmount()*creditTerm.getDiscount();
        setEarlyRebate(rebate);
    }
    
    public boolean isNormal(){
        return getType()==InvoiceType.normal;
    }
    
    public boolean isCIA(){
        return getType()==InvoiceType.cashInAdvance;
    }
    
    public boolean isReminder(){
        return getType()==InvoiceType.reminder;
    }
    
    public boolean discountPenaltyApply(){
        return getType()!=InvoiceType.cashInAdvance;
    }
    
    public boolean isToBePosted(){
        return getStatus()==InvoiceStatus.draft;
    }
    
    public boolean isToBePaid(){
        return getStatus()==InvoiceStatus.posted && payment==null;
    }
    
    public boolean isToBeReceipt(){
        return getStatus()==InvoiceStatus.paid && receipt==null;
    }
    
    public boolean isPaid(){
        return payment!=null;
    }
    
    public HashMap<CompletedGoodsEntity, Double> productToWorth(){
        HashMap<CompletedGoodsEntity, Double> productToWorth= new HashMap<CompletedGoodsEntity, Double>();
        for(ProductQuantityPriceEntity pqp : billingRequest.calculatePQPs()){
            Double price = productToWorth.get(pqp.getProduct());
            if(price==null){
                price = 0.0;
            }
            productToWorth.put((CompletedGoodsEntity)pqp.getProduct(), price+pqp.getPrice());
        }
        return productToWorth;
    }
    
    public boolean isDisplayCIA(){
        boolean display = false;
        if(!isNormal())
            return display;
        
        BillingRequestEntity requestCIACountedTowards 
                = billingRequest.getSalesOrder().getCashPayableAccountedFor();
        if(billingRequest.equals(requestCIACountedTowards))
            display = true;
        return display;
    }

    @Override
    public String childToString() {
        return "CustomerInvoiceEntity{" + "amount=" + amount + ", latePenalty=" + latePenalty + ", earlyRebate=" + earlyRebate + ", dueDate=" + dueDate + ", discountDueDate=" + discountDueDate + ", type=" + type + ", status=" + status + ", billingRequest=" + billingRequest + ", customerAccount=" + customerAccount + ", payment=" + payment + ", receipt=" + receipt + '}';
    }
    
}
